package week_08;

/**
 * 1334. 阈值距离内邻居最少的城市
 * 有 n 个城市，按从 0 到 n-1 编号。给你一个边数组 edges，其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边，距离阈值是一个整数 distanceThreshold。
 * <p>
 * 返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市，则返回编号最大的城市。
 * <p>
 * 注意，连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * <p>
 * <p>
 * 输入：n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4
 * 输出：3
 * 解释：城市分布图如上。
 * 每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是：
 * 城市 0 -> [城市 1, 城市 2]
 * 城市 1 -> [城市 0, 城市 2, 城市 3]
 * 城市 2 -> [城市 0, 城市 1, 城市 3]
 * 城市 3 -> [城市 1, 城市 2]
 * 城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市，但是我们必须返回城市 3，因为它的编号最大。
 * 示例 2：
 * <p>
 * <p>
 * <p>
 * 输入：n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2
 * 输出：0
 * 解释：城市分布图如上。
 * 每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是：
 * 城市 0 -> [城市 1]
 * 城市 1 -> [城市 0, 城市 4]
 * 城市 2 -> [城市 3, 城市 4]
 * 城市 3 -> [城市 2, 城市 4]
 * 城市 4 -> [城市 1, 城市 2, 城市 3]
 * 城市 0 在阈值距离 2 以内只有 1 个邻居城市。
 */
public class FindTheCity_1334 {
    /**
     * floyd算法
     * dp[i,j] =min(dp[i][j],dp[i][k]+dp[k][j])
     * k<j
     */


    public int findTheCity(int n, int[][] edges, int distanceThreshold) {
        /**
         *
         *          朴素想法  计算每个点能够到达的城市个数 返回城市数最小的 编号最大的城市
         *          需要先计算出 每个城市到别的城市的最小距离,才能遍历答案
         *          自己到自己为0
         *          邻接矩阵初值：i到i长度为0，没有边长度为INF，其余为输入的边
         *          程序大体流程是对的 但是细节是错的
         *          1.状态方程赋的初始值 自己为0 其他为 无穷大 即到不了
         *            edges 能到双向边赋值边值
         *            编号从0开始
         *          2.动态规划方程式状态 迭代
         *          3.计算更新答案
         */


        int[][] dp = new int[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                dp[i][j] = (int) 1e9;
        for (int i = 0; i < n; i++) dp[i][i] = 0;

        for (int i = 0; i < edges.length; i++) {
            int x = edges[i][0], y = edges[i][1], z = edges[i][2];
            dp[x][y] = z;
            dp[y][x] = z;
        }
        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k][j]);
                }
            }
        }

        int ans = 0;
        int[] counts = new int[n];
        for (int i = 0; i < n; i++) {
            int count = 0;
            for (int j = 0; j < n; j++) {
                if (dp[i][j] <= distanceThreshold) count++;
            }
            counts[i] = count;
            if (counts[i] <= counts[ans]) ans = i;
        }
        return ans;
    }
}
